

package com.vst.util;



import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

//import org.apache.log4j.Logger;


public class DAO<T extends Entidad> implements IDAO<T> {
	
 // private static Logger   log      = Logger.getLogger(DAO.class);

  private Class<Entidad>  clazz;

  protected String        sqlQuery = null;

  protected Query         q        = null;

  protected EntityManager em;
  
  @SuppressWarnings("unchecked")
  public DAO( ) {
    clazz = (Class<Entidad>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    //log.info("Crea aspecto de la Entidad:" + clazz.getName());
  }
  
  @PersistenceContext
  public void setEm(EntityManager em) {
	  //  log.info("Asignacion del EntityManager:" + clazz.getName() + " em: " + em.toString());
    this.em = em;
  }
  
  @SuppressWarnings("unchecked")
  public T get(Integer id) {
    try {
    	//    log.info(" Entro al metodo get de Entidad " + clazz.getName() + " con id:" + id);
      return (T) em.find(clazz, id);
    }
    catch(Exception e) {
      return null;
    }
  }

  @SuppressWarnings({"unchecked","cast"})
  public List<T> getTodos( ) {
    Entity e = (Entity) clazz.getAnnotation(Entity.class);
    String nombre = null;
    if(e == null || e.name() == null || e.name().length() == 0)
      nombre = clazz.getSimpleName();
    else
      nombre = e.name();
    String sql = "SELECT e FROM " + nombre + " e";
    // log.info(" Entro al metodo getTodos de Entidad " + clazz.getName() + "  con query: " + sql);
    return em.createQuery(sql).getResultList();
  }
  
  public void guardar(T objeto) {

    // EntityManager emReg=emf.createEntityManager();
    try {
    	//  log.warn(" Entro al metodo guardar de Entidad " + clazz.getName());
      // emReg.getTransaction().begin();
    	//  log.warn(" Transaction abierta  " + clazz.getName() + " con id :" + objeto.getId());

      if(objeto.getId() != null)
        em.merge(objeto);
      else
        em.persist(objeto);

      //log.warn(" Transaction terminada  " + clazz.getName() + " con id :" + objeto.getId());
      // emReg.getTransaction().commit();
      // log.warn(" Transaction commint  " + clazz.getName());
    }
    catch(Exception e) {
      System.err.println("Error:" + e.getMessage());
      //  log.error(" Transaction rollback  " + clazz.getName() + " error: " + e.getMessage());
      e.printStackTrace();
      em.getTransaction().rollback();
    }
    finally {
      /*
       * if(emReg != null) emReg.close();
       */
    	// log.warn(" Transaction cerrada  " + clazz.getName());
    }

  }
  
  public void eliminar(T objeto) {

    // EntityManager emReg=emf.createEntityManager();

    try {
    	//  log.warn(" Entro al metodo eliminar de Entidad " + clazz.getName());
      // emReg.getTransaction().begin();
    	//  log.warn(" Transaction abierta  " + clazz.getName() + " con id :" + objeto.getId());
      // emReg.refresh(objeto);
      // objeto = (T) emReg.find(objeto.getClass(),objeto.getId());
      if(objeto.getId() != null)
        em.remove(objeto);

      //log.warn(" Transaction terminada  " + clazz.getName() + " con id :" + objeto.getId());
      // emReg.getTransaction().commit();
      //log.warn(" Transaction commint  " + clazz.getName());
    }
    catch(Exception e) {
      System.err.println("Error:" + e.getMessage());
      // log.error(" Transaction rollback  " + clazz.getName() + " error: " + e.getMessage());
      e.printStackTrace();
      // em.getTransaction().rollback();
    }
    finally {
      // if(emReg != null)
      // emReg.close();
    	// log.warn(" Transaction cerrada  " + clazz.getName());
    }

  }
  
  @SuppressWarnings("unchecked")
  public T obtenerPorCodigo(String codigo , String campoCodigo) {
    Entity e = (Entity) clazz.getAnnotation(Entity.class);
    String nombre = null;
    if(e == null || e.name() == null || e.name().length() == 0)
      nombre = clazz.getSimpleName();
    else
      nombre = e.name();
    String sql = "SELECT e FROM " + nombre + " e  where e." + campoCodigo + " = :codigo";
    // log.info(" Entro al metodo obtenerPorCodigo de Entidad " + clazz.getName() + "  con query: " + sql);
    return (T) em.createQuery(sql).setParameter("codigo", codigo).getSingleResult();
  }

  @SuppressWarnings("unchecked")
  public T obtenerPorCodigo(String codigo) {
    Entity e = (Entity) clazz.getAnnotation(Entity.class);
    String nombre = null;
    if(e == null || e.name() == null || e.name().length() == 0)
      nombre = clazz.getSimpleName();
    else
      nombre = e.name();
    String sql = "SELECT e FROM " + nombre + " e  where e.codigo = " + codigo;
    // log.info(" Entro al metodo obtenerPorCodigo de Entidad " + clazz.getName() + "  con query: " + sql);
    return (T) em.createQuery(sql).getSingleResult();
  }

}
